<template>
  <div class="box" :class="{ file_none: !showFileList }">
    <el-upload
      action=""
      :accept="accept"
      :limit="limit"
      v-model:file-list="_fileList"
      :show-file-list="showFileList"
      class="upload-demo width_100"
      :ref="(el) => (fileUpload = el)"
      :http-request="fnUploadRequest"
      :before-upload="handleUpload"
      :on-preview="onPreview"
      :on-remove="onPemove"
    >
      <VabButton
        type="primary"
        :disabled="limit == _fileList.length || disabled"
        :title="title"
        :style="style"
      />

      <template #tip>
        <div class="el-upload__tip" v-if="tip">
          {{ tip }}
        </div>
      </template>
    </el-upload>
  </div>
</template>

<script lang="ts" setup>
  import { ElMessage, dayjs } from 'element-plus'
  import { EstimatedTime, StrSplit } from '~/src/utils/utils'
  import { AxiosPromise } from 'axios'
  import request from '~/src/utils/request'
  /**
   * @props
   */

  const props = defineProps({
    // 导入按钮标题
    title: {
      type: String,
      default: '导入',
    },
    // 接口
    api: {
      type: String,
      default: '',
    },
    // osss接口
    ossApi: {
      type: String,
      default: '/api_dms/file/getosssts',
    },
    // 参数
    query: {
      type: Object,
      default: () => {
        return {}
      },
    },
    // 文件类型
    accept: {
      type: String,
      default: '.xlsx', //'.xlsx,.doc,.pdf' 多文件格式
    },
    // 目录
    directory: {
      type: String,
      default: '',
    },
    // 是否显示文件信息
    showFileList: {
      type: Boolean,
      default: true,
    },
    // 限制
    limit: {
      type: Number,
      default: 1,
    },
    // 按钮样式
    style: {
      type: Object,
      default: {},
    } as any,
    // 提示语
    tip: {
      type: String,
      default: '',
    },
    // 限制文件大小【MB】
    size: {
      type: Number,
      default: '',
    },
    // 禁用
    disabled: {
      type: Boolean,
      default: false,
    },
  })
  /**
   * @var
   */
  // 全局提示
  const proxy: any = getCurrentInstance()?.proxy
  // 实例
  const fileUpload = ref()
  // 文件名称
  const fileName = ref('')
  // 时间
  const todayKey = dayjs().format('YYYY-MM-DD') //当前时间2023-08-07
  // 文件夹
  const folderName = 'dms' + props.directory //dms/xxx/20230405/xxxx.jpg

  // 获取阿里云STS
  const getosssts: () => AxiosPromise = () => request(props.ossApi)

  // 文件上传接口
  const ImportOrExport: (data: object) => AxiosPromise = (data) =>
    request(props.api, { data })

  const emit = defineEmits(['Refresh', 'exposePath'])

  // 数据
  let _fileList = ref<any>([])

  /**
   * @method
   */
  // 请求
  const fnUploadRequest = async (options: any) => {
    const { onSuccess, onProgress, onError, file } = options
    fileName.value = file.name
    try {
      const configRes = await getosssts()
      const client = new OSS({
        region: configRes.data.regionId,
        accessKeyId: configRes.data.AccessKeyId,
        accessKeySecret: configRes.data.AccessKeySecret,
        // 从STS服务获取的安全令牌（SecurityToken）。
        stsToken: configRes.data.SecurityToken,
        // 填写Bucket名称，例如examplebucket。
        bucket: configRes.data.roleSessionName, // bucket名字
        secure: true,
      })

      const chunkSize = 1024 * 1024 * 1 // 分片大小
      const chunks = Math.ceil(file.size / chunkSize) // 分片数量
      ElMessage(`预计本次上传需要${EstimatedTime(chunks)}`)
      const updateName = `${folderName}/${todayKey}/${file.name}`
      const porps: any = {
        // 获取分片上传进度、断点和返回值。
        progress: (p: any, cpt: any, res: any) => {
          onProgress({ percent: p * 100 })
          // setProgress(p * 100)
        },
        headers: {},
        parallel: chunks,
        partSize: chunkSize,
        meta: { year: dayjs().format('YYYY'), people: `${folderName}` },
        mime: 'text/plain',
      }
      client
        .multipartUpload(`${updateName}`, file, { ...porps })
        .then((res: any) => {
          onSuccess(res, file)
          const requestUrls = res.res.requestUrls[0]
          const path = StrSplit(requestUrls, '?', 0)

          _fileList.value = [{ name: file.name, url: path }]

          // 暴露oss地址
          emit('exposePath', path)

          if (!props.api) return

          ImportOrExport({
            ...props.query,
            path,
          })
            .then((res) => {
              emit('Refresh')
            })
            .catch(() => {
              ElMessage({
                message: '失败',
                type: 'error',
              })
            })
        })
        .catch(function (err: any) {
          ElMessage({
            message: '上传失败',
            type: 'error',
          })
        })
    } catch (error) {}
  }
  // 上传前
  const handleUpload = (file: any) => {
    const { size } = file

    // 是否超出限制大小
    let isExceedSize = false

    if (props.size) {
      isExceedSize = size / 1024 / 1024 > props.size

      if (isExceedSize) {
        proxy.$Message(`上传文件大小不能超过 ${props.size}MB!`, 'warning')
        return false
      }
    }
  }
  // 预览
  const onPreview = (file: any) => {
    window.open(file.url)
  }
  // 删除
  const onPemove = (file: any) => {
    _fileList.value = []
    emit('exposePath', '')
  }

  /**
   * @实例
   */
  // 组件实例
  defineExpose({
    list: _fileList,
  })
</script>

<style lang="scss" scoped>
  .default_text {
    padding-top: 12px;
  }

  .box {
    width: 100%;

    :deep() {
      .el-upload-dragger {
        height: 100%;
        line-height: 80px;
      }

      .el-upload-list__item.is-success.focusing .el-icon-close-tip {
        display: none !important;
      }

      .el-icon--close-tip {
        display: none !important;
      }
      .el-upload {
        width: 100%;
        display: flex;
        justify-content: flex-start;
      }
    }
  }

  .file_none {
    .el-upload-list {
      display: none;
    }
  }
</style>
